package com.i.template.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.i.template.constant.RedisConstants;
import com.i.template.domain.UserDO;
import com.i.template.domain.vo.PageVO;
import com.i.template.domain.vo.UserLogin;
import com.i.template.domain.vo.UserVO;
import com.i.template.mapper.UserMapper;
import com.i.template.service.IUserService;
import com.i.template.util.JWTUtils;
import com.i.template.util.UserHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lewis
 * @since 2024/7/24
 * @type class
 * @description 用户 服务层
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements IUserService {

    private final StringRedisTemplate stringRedisTemplate;
    @Override
//    @Transactional
    public UserVO login(UserLogin userLogin) {
        UserDO userDO = lambdaQuery().eq(UserDO::getEmail,userLogin.getEmail()).eq(UserDO::getPassword,userLogin.getPassword()).one();
        if(userDO == null) {
            return null;
        }
        UserVO userVO = BeanUtil.copyProperties(userDO, UserVO.class);
        String token = JWTUtils.createToken(userDO);
        userVO.setToken(token);
        return userVO;
    }

    @Override
    public PageVO<UserVO> pageByUserInfo(Long current, Long size) {
        IPage<UserDO> userDOIPage = new Page<>(current,size);
        IPage<UserDO> page = lambdaQuery().page(userDOIPage);
        List<UserVO> userVOS = page.getRecords()
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserVO.class))
                .collect(Collectors.toList());
        PageVO<UserVO> userVOPageVO = PageVO
                .<UserVO>builder()
                .total(page.getTotal())
                .records(userVOS)
                .current(page.getCurrent())
                .size(page.getSize()).build();
        return userVOPageVO;
    }

    @Override
    public void sign() {
        Long userId = UserHolder.getUser();
        LocalDateTime now = LocalDateTime.now();
        String keySuffix =  now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
        int dayOfMonth = now.getDayOfMonth();
        stringRedisTemplate.opsForValue().setBit(
                key,
                dayOfMonth - 1,
                true
        );
        return;
    }
    @Override
    public Integer signCount() {
        Long userId = UserHolder.getUser();
        LocalDateTime now = LocalDateTime.now();
        String keySuffix =  now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
        int dayOfMonth = now.getDayOfMonth();
        List<Long> result = stringRedisTemplate.opsForValue()
                .bitField(
                        key,
                        BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
                );
        if(result == null || result.isEmpty()) {
            return 0;
        }
        Long num = result.get(0);
        if(num == null || num == 0) {
            return 0;
        }
        int count = 0;
        while (true) {
            if((num & 1) == 0) {
                break;
            }else {
                count ++;
            }
            num >>>= 1;
        }
        return count;
    }

    @Override
    public Boolean signInStatus() {
        Long userId = UserHolder.getUser();
        LocalDateTime now = LocalDateTime.now();
        String keySuffix =  now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
        int dayOfMonth = now.getDayOfMonth();
        return stringRedisTemplate.opsForValue().getBit(key, dayOfMonth-1);
    }

    @Override
    public List<UserVO> genderStatistics() {
        QueryWrapper<UserDO> userDOQueryWrapper = new QueryWrapper<>();
        userDOQueryWrapper.select("count(*)");
        List<UserDO> userDOS = query().groupBy("gender").select("gender,count(*) as count").list();
        return BeanUtil.copyToList(userDOS,UserVO.class);
    }
    //
        // 获取代理对象(事务)
//        IUserService o = (IUserService) AopContext.currentProxy();
}
